#include"magic_enum.hpp"
#include "udpserver.h"
#include<future>
#include<vector>
#include<algorithm>
#include<QNetworkDatagram>
#include<QRegularExpression>

unsigned short UDPServer::m_id=0;

UDPServer::UDPServer()
{
    m_udpSocket=new QUdpSocket(this);
    if(!m_udpSocket->bind(QHostAddress::LocalHost,7755)){
        qDebug()<<m_udpSocket->errorString();
    }

    connect(m_udpSocket,SIGNAL(readyRead()),this,SLOT(readPendingDatagrams()));
    connect(this,SIGNAL(MsgArrive(bool)),this,SLOT(doWorkOnMsg(bool)));
}

std::queue<UDPServer::msgStartInfo *> UDPServer::CreateStartStatusQueue(const QRegularExpressionMatchIterator &remi)
{
    decltype(msgHeadQueue) msiQue;
    for(const auto &r:remi){
        if(!r.hasMatch())   continue;
        msgStartInfo *msi=new msgStartInfo;
        msi->msgIndex=r.captured().section('-',0,0).toInt();
        msi->address=QHostAddress(r.captured().section('-',1,1));
        msi->action=magic_enum::enum_cast<UDPServer::ServerAction>(r.captured().section('-',2,2).toStdString()).value();
        msi->startRelaPos=r.capturedStart();
        msi->endRelaPos=r.capturedEnd();

        qDebug()<<r.captured();
        qDebug()<<"sPos:"<<msi->startRelaPos<<"--"<<"SePos:"<<msi->endRelaPos;

        msiQue.push(msi);
    }
    return msiQue;
}

std::queue<UDPServer::msgEndInfo *> UDPServer::CreateEndStatusQueue(const QRegularExpressionMatchIterator &remi)
{
    decltype(msgTailQueue) meiQue;
    for(const auto &r:remi){
        if(!r.hasMatch())   continue;
        msgEndInfo *mei=new msgEndInfo;
        mei->msgIndex=r.captured().section('-',2,2).toInt();
        mei->address=QHostAddress(r.captured().section('-',1,1));
        mei->startRelaPos=r.capturedStart();
        mei->endRelaPos=r.capturedEnd();

        qDebug()<<r.captured();
        qDebug()<<"ePos:"<<mei->startRelaPos<<"--"<<"ePos:"<<mei->endRelaPos;


        meiQue.push(mei);
    }
    return meiQue;
}

void UDPServer::sendMsgtoFunc(std::queue<msgStartInfo *> &&si, std::queue<msgEndInfo *> &&ei, const QString &c)
{
    if(si.empty()&&ei.empty())  return;
    int postEndPos=0;   //前一个msgEndInfo->endRelaPos
    std::vector<std::pair<msgStartInfo *,int>> execSInfoVec;    //异常头信息集合
    std::vector<std::pair<msgEndInfo *,int>> execEInfoVec;      //异常尾信息集合

    while(!si.empty()&&!ei.empty()){
        msgStartInfo *msi=si.front();
        //si.pop();
        msgEndInfo *mei=ei.front();
        //ei.pop();

        if(msi->msgIndex==mei->msgIndex&&msi->address==mei->address){
            int pos=msi->endRelaPos+4;
            int size=mei->startRelaPos-4-pos;
            this->mainProceFunc(c.sliced(pos,size),msi->action);
            qDebug()<<"**********"<<c.sliced(pos,size)<<"***************";

            si.pop();
            ei.pop();
            postEndPos=mei->endRelaPos;
            delete msi;
            delete mei;
        }

        //当头尾序号不一致的时候，处理信息
        if(msi->msgIndex!=mei->msgIndex&&msi->address==mei->address){
            if(msi->msgIndex<mei->msgIndex){
                si.pop();
                execSInfoVec.emplace_back(std::make_pair(msi,si.front()->startRelaPos));
            }
            else{
                ei.pop();
                execEInfoVec.emplace_back(std::make_pair(mei,postEndPos));
            }
        }
    }

    int i=0;
    std::vector<char> hasLinked(execEInfoVec.size(),'0');   //表示execEInfoVec中某个元素是否能成功匹配，0成功，1失败
    while(i!=execSInfoVec.size()){
        auto iter=std::find_if(execEInfoVec.begin(),execEInfoVec.end(),
                               [&execSInfoVec,&i](const std::pair<msgEndInfo *,int>& p){
            return p.first->msgIndex==execSInfoVec[i].first->msgIndex;
        });
        if(iter==execEInfoVec.end()){
            QString b=QString::number(execSInfoVec[i].first->msgIndex).prepend("0:");
            this->mainProceFunc(b,UDPServer::ERROR);
        }
        else
            hasLinked[iter-execEInfoVec.begin()]='1';
        QString jsonByte=c.sliced(execSInfoVec[i].first->endRelaPos+4,execSInfoVec[i].second-execSInfoVec[i].first->endRelaPos+4)+
                         c.sliced(iter->second,iter->first->startRelaPos-4);
        this->mainProceFunc(jsonByte,execSInfoVec[i].first->action);
    }
    for(int j=0;j!=hasLinked.size()&&!execEInfoVec.empty();++j){
        (hasLinked[j]=='0') ? delete execEInfoVec[j].first : void();
    }
    execSInfoVec.clear();
    execEInfoVec.clear();

}

void UDPServer::mainProceFunc(const QString &msg, const ServerAction &action)
{
    if(action==UDPServer::LOGIN){
        this->loginFunc(msg);
    }
    else if(action==UDPServer::NONE){
        this->logoutFunc(msg);
    }
    else if(action==UDPServer::REGISTER){
        this->registerFunc(msg);
    }
    else if(action==UDPServer::OTHER){
        this->otherFunc(msg);
    }
    else if(action==UDPServer::NONE){
        ;
    }
    else if(action==UDPServer::ERROR){
        this->errorFunc(msg);
    }
    else{
        return;
    }
}

void UDPServer::loginFunc(const QString &msg)
{
    int l=m_udpSocket->writeDatagram(msg.toUtf8(),QHostAddress::LocalHost,3355);
}

void UDPServer::logoutFunc(const QString &msg)
{

}

void UDPServer::registerFunc(const QString &msg)
{

}

void UDPServer::otherFunc(const QString &msg)
{

}

void UDPServer::errorFunc(const QString &msg)
{

}

void UDPServer::readPendingDatagrams()
{
    if(m_udpSocket->hasPendingDatagrams()){
        int len=m_udpSocket->pendingDatagramSize();
        QNetworkDatagram data=m_udpSocket->receiveDatagram(len);
        if(!data.isValid()){
            qDebug()<<m_udpSocket->localPort()<<m_udpSocket->error();
            m_udpSocket->writeDatagram(data.makeReply("0"));
            return;
        }
        msgQueue.push(data.data());

        emit MsgArrive(!msgQueue.empty());
    }
}

void UDPServer::doWorkOnMsg(bool isArrive)
{
    while(!msgQueue.empty()){
        const QString msg=msgQueue.front();
//        QByteArray msg(msgQueue.front());
        msgQueue.pop();

//        QRegularExpression re1("(?:: --).*(?:-- :)");    //匹配中间真实数据
        QRegularExpression re2("\\d+-(?:(?:\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])-[A-Z]+");    //匹配开头标记
        QRegularExpression re3("end-(?:(?:\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])-\\d+");       //匹配每句话结尾标记

        auto reStartStatus=re2.globalMatch(msg);
        auto reEndStatus=re3.globalMatch(msg);

        qDebug()<<"***************************";
        std::future<std::queue<msgStartInfo *>> f1=std::async(&UDPServer::CreateStartStatusQueue,this,reStartStatus);
        std::future<std::queue<msgEndInfo *>> f2=std::async(&UDPServer::CreateEndStatusQueue,this,reEndStatus);

        auto f3=std::async(std::launch::async,&UDPServer::sendMsgtoFunc,this,std::move(f1.get()),std::move(f2.get()),msg);
        qDebug()<<"***************************";
    }
}
